<?php

interface ApiClient
{
    public function setVariable($name, $var);
    public function getHtml($template);
}

class StemwareSdkBase implements ApiClient 
{
    var $version = "1.2";
    var $errorMessage;
    var $errorCode;
    
    /**
     * Cache the information on the API location on the server
     */
    var $apiUrl;
    
    /**
     * Default to a 300 second timeout on server calls
     */
    var $timeout = 300; 
    
    /**
     * Default to a 8K chunk size
     */
    var $chunkSize = 8192;
    
    /**
     * Cache the user api_key so we only have to log in once per client instantiation
     */
    var $api_key;

    /**
     * Cache the user api_key so we only have to log in once per client instantiation
     */
    var $secure = false;
    
    /**
     * Connect to the Wine.com API for a given list. All MCAPI calls require login before functioning
     * 
     * @param string $username_or_apikey Your Wine.com login user name OR apikey - always required
     * @param string $password Your Wine.com login password - only required when username passed instead of API Key
     */
    private function StemwareSdkBase($username_or_apikey, $password=null, $secure=false) {
        //do more "caching" of the uuid for those people that keep instantiating this...
        $this->secure = $secure;
        $this->apiUrl = parse_url("http://api.mailchimp.com/" . $this->version . "/?output=php");
        if ( isset($GLOBALS["mc_api_key"]) && $GLOBALS["mc_api_key"]!="" ){
            $this->api_key = $GLOBALS["mc_api_key"];
        } elseif( $username_or_apikey && !$password ){
            $this->api_key = $GLOBALS["mc_api_key"] = $username_or_apikey;
        }  else {
            $this->api_key = $this->httpRequest("login", array("username" => $username_or_apikey, "password" => $password));
            $GLOBALS["mc_api_key"] = $this->api_key;
        }
    }
    
    public static function getInstant()
    {
    	
    }
    
    /**
     * 
     * the magic method _clone is implemented to stop
     * cloning of singleton object. So the class will  
     * safely remain the single point of sinchronization 
     * for the whole library
     * 
     */
    protected function _clone(){
    	throw new Exception('Cloning of singleton class StemwareSDK is not allowed');
    }
    
    function setTimeout($seconds){
        if (is_int($seconds)){
            $this->timeout = $seconds;
            return true;
        }
    }
    
    function getTimeout(){
        return $this->timeout;
    }
    
    function useSecure($val){
        if ($val===true){
            $this->secure = true;
        } else {
            $this->secure = false;
        }
    }
       
    /**
     * Actually connect to the server and call the requested methods, parsing the result
     * You should never have to call this function manually
     */
    private function httpRequest($method, $params) {
    	//Always include the apikey if we are not logging in
    	if($method != "login") {
    		$params["apikey"] = $this->api_key;
    	}
        $this->errorMessage = "";
        $this->errorCode = "";
        $post_vars = $this->prepareHttpQuery($params);
        
        $payload  = "POST " . $this->apiUrl["path"] . "?" . $this->apiUrl["query"] . "&method=" . $method . " HTTP/1.0\r\n";
        $payload .= "Host: " . $this->apiUrl["host"] . "\r\n";
        $payload .= "User-Agent: StremwareSDK/" . $this->version ."\r\n";
        $payload .= "Content-type: application/x-www-form-urlencoded\r\n";
        $payload .= "Content-length: " . strlen($post_vars) . "\r\n";
        $payload .= "Connection: close \r\n\r\n";
        $payload .= $post_vars;
        
        ob_start();
        if ($this->secure){
            $sock = fsockopen("ssl://".$this->apiUrl["host"], 443, $errno, $errstr, $this->timeout);
        } else {
            $sock = fsockopen($this->apiUrl["host"], 80, $errno, $errstr, $this->timeout);
        }
        if(!$sock) {
            $this->errorMessage = "Could not connect (ERR $errno: $errstr)";
            $this->errorCode = "-99";
            ob_end_clean();
            return false;
        }
        
        $response = "";
        fwrite($sock, $payload);
        while(!feof($sock)) {
            $response .= fread($sock, $this->chunkSize);
        }
        fclose($sock);
        ob_end_clean();
        
        list($throw, $response) = explode("\r\n\r\n", $response, 2);
        
        if(ini_get("magic_quotes_runtime")) $response = stripslashes($response);
        
        $serial = unserialize($response);
        if($response && $serial === false) {
        	$response = array("error" => "Bad Response.  Got This: " . $response, "code" => "-99");
        } else {
        	$response = $serial;
        }
        if(is_array($response) && isset($response["error"])) {
            $this->errorMessage = $response["error"];
            $this->errorCode = $response["code"];
            return false;
        }
        
        return $response;
    }
    
    /**
     * 
     * Re-implement http_build_query for systems that do not already have it
     * 
     */
   private function prepareHttpQuery($params, $key=null) {
        $ret = array();
        
        foreach((array) $params as $name => $val) {
            $name = urlencode($name);
            if($key !== null) {
                $name = $key . "[" . $name . "]";
            }
            
            if(is_array($val) || is_object($val)) {
                $ret[] = $this->prepareHttpQuery($val, $name);
            } elseif($val !== null) {
                $ret[] = $name . "=" . urlencode($val);
            }
        }
        
        return implode("&", $ret);
    }
}

?>